package com.xu.crawler.acceptor;

import com.xu.crawler.config.timeWaitingStrategy.TimeWaitingStrategy;
import com.xu.crawler.enums.URLMapperEnum;
import com.xu.crawler.remote.AbstractRemoteService;
import com.xu.crawler.remote.RemoteAcceptor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.rmi.RemoteException;
import java.util.function.Consumer;
import java.util.function.Function;

/**
 * Created by clear on 2018/7/10.
 */
public abstract class AbstractAcceptor<T> extends AbstractRemoteService implements
        Consumer<T>,
        Function<T, T>,
        RemoteAcceptor<T> {

    private final static Logger log = LoggerFactory.getLogger(AbstractAcceptor.class);


    protected abstract void consumeLogic(T t) throws Exception;


    @Override
    public void accept(T t) {
        int retryTime = this.strategy.retryTimes();
        try {
            int loopTime = 1;
            while (retryTime > loopTime) {
                try {
                    consumeLogic(t);
                    break;
                } catch (Exception e) {
                    log.error("Acceptor: Network busy Retrying -> {} times", loopTime);
                    if (!(e instanceof IOException)) throw e;
                    this.strategy.waiting(loopTime++);
                }
            }

        } catch (Exception e) {
            log.error("{} accept fail {}", this.getClass().getName(), e);
        }

    }

    @Override
    public T apply(T t) {
        accept(t);
        return t;
    }

    public AbstractAcceptor() throws RemoteException {
        this(null);
    }

    public AbstractAcceptor(TimeWaitingStrategy strategy) throws RemoteException {
        this(strategy, URLMapperEnum.MAIN_PAGE.toString());
    }

    public AbstractAcceptor(TimeWaitingStrategy strategy, String webSite) throws RemoteException {
        super(strategy, webSite);
    }
}
